#pragma once
#include "lib\TCollection.h"
#include "model\Sport.h"
#include "model\Team.h"
#include "model\Match.h"
#include <vector>

class PointCalculator;

class Division : public BaseModel {
public:
  typedef std::map<std::string, Match> InnerMatchMap;
  typedef std::map<std::string, InnerMatchMap> OuterMatchMap;
  typedef std::pair<OuterMatchMap::const_iterator, OuterMatchMap::const_iterator> OuterMatchPair;
  typedef std::pair<InnerMatchMap::const_iterator, InnerMatchMap::const_iterator> InnerMatchPair;
  typedef TCollection<Team>::IterBoolPair IterBoolPair;
  typedef std::pair<InnerMatchMap::const_iterator, bool> MatchBoolPair;


  // constructors
  Division();
  explicit Division(std::string name);

  // mutator
  void set_name(std::string name) {
    name_ = name;
  }

  // accessor
  std::string name() const;

  // team related functions (using set)
  IterBoolPair AddTeam(Team& team);
  IterBoolPair FindTeam(Team& team) const;
  TCollection<Team>::CollectionPair GetTeams() const;
  void DeleteTeam(std::set<Team>::iterator iter);
  int NumTeams() const;

  
  // match related functions (using map)
  MatchBoolPair FindMatch(Match& match) const;
  OuterMatchPair GetMatchIters() const;
  InnerMatchPair GetMapMatches(const OuterMatchMap::const_iterator iter) const;
  int NumMatches() const;
  void AddMatch(const Match& match);
  void AddResult(const Match& match);
  bool ValidateResult(Match& match) const;
   
  // comparison operators
  int operator==(const Division& division) const;
  bool operator<(const Division& division) const;
  
  // validation function
  virtual bool Validate();
  
  // attach calculator type to object
  void InjectCalculator(PointCalculator *calc);



private:
  std::string NameChars();

  friend std::istream& operator>>(std::istream& in,  Division& division);
  friend std::ostream& operator<<(std::ostream& out, const Division& division);

  std::string name_;
  TCollection<Team> teams_;
  std::map< std::string, std::map<std::string, Match> > matches_;
  PointCalculator *calc_;

};